import {
    ActionFunctionArgs,
    LoaderFunctionArgs,
    redirect,
} from "@remix-run/cloudflare";
import React, { useState, useRef, useMemo, useEffect } from "react";
import Image from "remix-image";
import { Button } from "~/components/ui/button";
import {
    TOKEN,
    TRANSFER_WORKFLOW_ID,
    createComfyOneAPI,
} from "~/services/onethingAI";
import { Card } from "~/components/ui/card";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Textarea } from "~/components/ui/textarea";
import { TaskData } from "~/models";
import {
    Form,
    useLoaderData,
    useRevalidator,
    useSubmit,
} from "@remix-run/react";
import AuthImage from "~/components/ui/auth-image";

export const action = async ({ request }: ActionFunctionArgs) => {
    console.log("action");

    try {
        const formData = await request.formData();
        const roomPhoto = formData.get("room");
        const materialPhoto = formData.get("material");
        const prompt = formData.get("prompt");
        const api = createComfyOneAPI();

        const roomPhotoResponse = await api.uploadFile(roomPhoto as File);
        const materialPhotoResponse = await api.uploadFile(
            materialPhoto as File
        );

        console.log({ roomPhotoResponse, materialPhotoResponse });
        if (roomPhotoResponse.code !== 0 || materialPhotoResponse.code !== 0) {
            return Response.json({
                code: 500,
                message: "图片上传失败",
            });
        }

        const taskResponse = await api.createTask({
            workflow_id: TRANSFER_WORKFLOW_ID,
            inputs: [
                {
                    id: 27,
                    params: {
                        image: roomPhotoResponse.data.Path,
                    },
                },
                {
                    id: 22,
                    params: {
                        image: materialPhotoResponse.data.Path,
                    },
                },
                {
                    id: 110,
                    params: {
                        prompt,
                    },
                },
            ],
            free_cache: false,
        });
        if (taskResponse.code === 0) {
            return redirect(
                `/features/transfer?taskId=${taskResponse.data.taskId}`
            );
        } else {
            return Response.json({
                code: taskResponse.code,
                message: taskResponse.message,
            });
        }
    } catch (error) {
        console.error("创建任务失败:", error);
        throw error;
    }
};

export const loader = async ({ request }: LoaderFunctionArgs) => {
    const url = new URL(request.url);
    const taskId = url.searchParams.get("taskId");
    console.log("taskId: " + taskId);
    if (!taskId) {
        return {};
    }
    const api = createComfyOneAPI();
    const resp = await api.getTaskStatus(taskId);

    return Response.json({ task: resp.data, taskId });
};

type LoaderData = {
    task: TaskData;
    taskId: string;
};

type ActionData = {
    code: number;
    message: string;
};

export default function StyleTransferPage() {
    const { task } = useLoaderData<LoaderData>();
    // const actionData = useActionData<ActionData>();
    const [isSubmitting, setIsSubmitting] = useState(false);

    const [roomPhotoPreview, setRoomPhotoPreview] = useState<string | null>(
        null
    );
    const [roomPhotoName, setRoomPhotoName] = useState<string>("");
    const [materialPhotoPreview, setMaterialPhotoPreview] = useState<
        string | null
    >(null);
    const [materialPhotoName, setMaterialPhotoName] = useState<string>("");
    const [prompt, setPrompt] = useState("");

    const roomPhotoInputRef = useRef<HTMLInputElement | null>(null);
    const materialPhotoInputRef = useRef<HTMLInputElement | null>(null);
    const revalidator = useRevalidator();

    const resultImage = task?.images?.[0] || "";

    const isDone = task != null;

    const handleFileChange = (
        event: React.ChangeEvent<HTMLInputElement>,
        setPreview: (url: string | null) => void,
        setFileName: (name: string) => void
    ) => {
        const file = event.target.files?.[0];
        if (file) {
            const url = URL.createObjectURL(file);
            setPreview(url);
            setFileName(file.name);
        }
    };

    const handleUploadClick = (
        inputRef: React.RefObject<HTMLInputElement | null>
    ) => {
        if (inputRef.current) {
            inputRef.current.click();
        }
    };

    const submit = useSubmit();

    const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        console.log("submit");

        const formData = new FormData(e.currentTarget);
        // const options: SubmitOptions = {
        //     action: "/features/transfer",
        //     method: "post",
        //     encType: "multipart/form-data",
        // };
        setIsSubmitting(true);
        submit(formData);
    };

    useEffect(() => {
        if (!task) {
            return;
        }

        const revalidate = () => {
            if (revalidator.state === "idle") {
                revalidator.revalidate();
            }
        };

        if (task.status === "finished") {
            setIsSubmitting(false);
        } else {
            setIsSubmitting(true);
            const timer = setTimeout(revalidate, 5000);
            return () => clearTimeout(timer);
        }
    }, [task, revalidator]);

    const imgHeaders = useMemo(
        () => ({
            Authorization: `Bearer ${TOKEN}`,
        }),
        []
    );

    const isValid = roomPhotoPreview && materialPhotoPreview && prompt;

    return (
        <section className="flex">
            <div className="flex flex-col space-y-4 p-4 w-1/3">
                <Form
                    id="transfer-form"
                    method="post"
                    encType="multipart/form-data"
                    onSubmit={handleSubmit}
                >
                    <div className="space-y-4">
                        <div className="space-y-2">
                            <Label>上传原始图片</Label>
                            <div className="flex items-center gap-4">
                                <Input
                                    type="file"
                                    accept="image/*"
                                    className="hidden"
                                    name="room"
                                    ref={roomPhotoInputRef}
                                    onChange={(e) =>
                                        handleFileChange(
                                            e,
                                            setRoomPhotoPreview,
                                            setRoomPhotoName
                                        )
                                    }
                                />
                                <div className="flex-1 rounded-md border border-input px-3 py-2 text-sm text-muted-foreground truncate">
                                    {roomPhotoName || "请选择图片"}
                                </div>
                                <Button
                                    type="button"
                                    variant="outline"
                                    onClick={() =>
                                        handleUploadClick(roomPhotoInputRef)
                                    }
                                >
                                    选择
                                </Button>
                            </div>
                            {roomPhotoPreview && (
                                <div className="relative w-full overflow-hidden rounded-lg border">
                                    <Image
                                        src={roomPhotoPreview}
                                        alt="Reference preview"
                                        className="object-contain"
                                    />
                                </div>
                            )}
                        </div>
                        <div className="space-y-2">
                            <Label>上传材质贴图</Label>
                            <div className="flex items-center gap-4">
                                <Input
                                    type="file"
                                    accept="image/*"
                                    className="hidden"
                                    name="material"
                                    ref={materialPhotoInputRef}
                                    onChange={(e) =>
                                        handleFileChange(
                                            e,
                                            setMaterialPhotoPreview,
                                            setMaterialPhotoName
                                        )
                                    }
                                />
                                <div className="flex-1 rounded-md border border-input px-3 py-2 text-sm text-muted-foreground truncate">
                                    {materialPhotoName || "请选择图片"}
                                </div>
                                <Button
                                    type="button"
                                    variant="outline"
                                    onClick={() =>
                                        handleUploadClick(materialPhotoInputRef)
                                    }
                                >
                                    选择
                                </Button>
                            </div>
                            {materialPhotoPreview && (
                                <div className="relative aspect-video w-full overflow-hidden rounded-lg border">
                                    <Image
                                        src={materialPhotoPreview}
                                        alt="Texture preview"
                                        className="object-contain"
                                    />
                                </div>
                            )}
                        </div>
                        <div className="space-y-2">
                            <Label>区域描述</Label>
                            <Textarea
                                name="prompt"
                                placeholder="请输入具体的区域描述，例如：正面的墙，左边的墙，地面..."
                                className="min-h-[100px]"
                                value={prompt}
                                onChange={(e) => setPrompt(e.target.value)}
                            />
                        </div>
                        <Button
                            className="w-full h-12"
                            type="submit"
                            disabled={isSubmitting || !isValid}
                        >
                            {isSubmitting ? "生成中..." : "生成设计图"}
                        </Button>
                    </div>
                </Form>
            </div>

            {resultImage ? (
                <div className="flex-1 p-4">
                    <Card className="overflow-hidden w-full">
                        <AuthImage
                            headers={imgHeaders}
                            src={resultImage}
                            alt="生成的设计图"
                            className="object-cover"
                        />
                    </Card>
                </div>
            ) : isDone ? (
                <div className="flex flex-1 justify-center items-center text-xl">
                    <div>图片生成中，请稍候...</div>
                    <div className="text-sm text-gray-500">
                        （预计需要3-5分钟）
                    </div>
                </div>
            ) : (
                <div className="flex flex-col flex-1 justify-center items-center text-xl">
                    <div>您尚未生成作品</div>
                </div>
            )}
        </section>
    );
}
